udp recvfrom阻塞吗

您所在的位置:网站首页 recvfrom 返回0 udp recvfrom阻塞吗

udp recvfrom阻塞吗

2023-03-30 01:36| 来源: 网络整理| 查看: 265

本文作者:PsgQ

本文链接:https://www.cnblogs.com/PsgQ/p/14089310.html

如何发送数据包?Q:当应用程序产生数据的时候,需要去构造数据包并发送到网络上去,但是由谁负责处理呢?A:现代操作系统负责数据包得构造与发送,应用程序只需提供数据。 当应用程序产生数据时,应用程序将数据交给OS内核,然后在OS内核添加各层的首部,构建好数据包,然后交给网卡,发送到网络中去。Q:应用程序如何向OS 发送数据呢?A: OS为程序提供了一个接口,即socket API,类似于系统调用函数。Q:通过socket API,只需要提供数据吗?A:并不,还需要告诉OS 内核,目的端口是什么,传输层使用哪种协议(UDP/TCP),目的IP地址。Q:为什么不需要告诉源端口?A:因为源端口是当数据进入到OS内核时,OS会为这个应用程序随机开放一个端口,作为源端口。当服务器端收到数据,进行返回时,也从这个端口进行返回。同样源IP地址,OS内核也是选一个网卡出去,这个网卡的地址作为源IP地址。

详情可见下图:

365753b59b47b0d09928c47c443bc7dd.pngQ:加工数据是包括什么?

A:依次包括添加传输层首部,网络层首部,所以在这里需要告诉传输层的目的端口,以及使用的协议,以及网络层的目的IP地址。然后交给网卡驱动程序,构造数据链路层头部,以及物理层。若想继续详细了解网卡的操作,可参考: 网卡工作原理详解 , 从网卡发送数据再谈TCP/IP协议—网络传输速度计算-网卡构造

了解到上述信息,知道我们要告诉OS 目的IP地址,目的端口,以及数据。

下面是使用python网络编程客户端的代码:

import socketip="127.0.0.1"port=8090data = b"hello PsgQ"sock=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)sock.sendto(data,(ip,port))Q: socket函数里面的参数是什么意思?A: socket.AF_INET表示使用IPv4。socket.SOCK_DGRAM表示传输层使用UDP。Q:为什么data=b"hello PsgQ"?A: 因为在网络中传输的是字节流,b前缀将字符串转换成bytes。对于英文字母可以这样转换,但对于中文字符串不行,因为b后面的字符串必须是ascii码可以表示的。若要传递中文字符串,须data=bytes('哈哈',encoding='UTF-8')

具体可参考 字符串和编码

c语言版代码随后更新。

如何接收数据包?

网卡驱动程序收到数据,作出校验以及检查完相应的目的MAC地址,交到OS内核。

OS内核 网络层模块 进行解封装,查看IP的目的地址,是不是发给自己的,丢弃IP地址不是自己的数据包。然后查看传输层使用的是什么协议,假如是UDP,之后交给UDP模块处理。

UDP获得数据包后,查看目的端口,发给相应的端口。

Q:应用程序怎么去获得数据阿?A:每个应用程序想要去接收数据,都需要与相应的端口进行绑定。比如HTTP,默认80端口,DNS默认使用53端口等。即OS内核交付给相应的端口,就意味着交付到某个应用程序(通过socket API)。相当于告诉内核,任何时候只要有数据到达这个端口,可以把数据交给我。具体过程是,OS 内核交给相应的端口的缓冲区,这个缓冲区是与端口进行绑定的。应用程序可从这个缓冲区读取数据。

实际情况可能是:当没有数据时,这个应用程序的socket API会被阻塞掉,但当数据包到达时,OS内核会去激活这个进程。

如下图:

38181d9e14abb48081cfd1f867696bd3.png

从上述信息了解到,我们在server端要进行绑定端口,因为可能有多个网卡,每个网卡IP地址不同,所以我们也要绑定IP地址等。

下面是使用python网络编程服务器端的代码:

import socketip="0.0.0.0"port = 8090sock=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)sock.bind((ip,port))while True: data,(ip,port)=sock.recvfrom(1024) data=data.decode('ascii') print("clinet:{},port:{}".format(ip,port)) print("Received:{}".format(data))Q: ip ="0.0.0.0"?A: 表示 数据包的目的地址可以是任意一个网卡的地址。Q: data=data.decode('ascii')A: 因为网络上使用的是字节流,前面客户端将字符串转换成了字节流,在这里使用ascii码进行解码,使字节流重又转换成字符串格式。

注意:调用bind函数 ,参数是(ip,port)

最终运行结果:

d083e9aa8615da9a9fb2268ac3df7231.png

c语言版代码随后更新。谢谢大家。

本文作者:PsgQ

本文链接:https://www.cnblogs.com/PsgQ/p/14089310.html



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3